package qy.jalgotrade.strategy;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import qy.jalgotrade.barfeed.BaseBarFeed;
import qy.jalgotrade.broker.backtesting.BacktestingBroker;

/**
 * <pre>
 * Base class for backtesting strategies.
 * 
 * .. note::
 *     This is a base class and should not be used directly.
 * </pre>
 * 
 * @author c-geo
 *
 */
public abstract class BacktestingStrategy extends BaseStrategy {

	private boolean __useAdjustedValues;

	/**
	 * 
	 * @param barFeed The bar feed to use to backtest the strategy.
	 */
	public BacktestingStrategy(BaseBarFeed barFeed) {

		this(barFeed, 1000000);
	}

	/**
	 * 
	 * @param barFeed The bar feed to use to backtest the strategy.
	 * @param cash    The starting capital or a broker instance.
	 */
	public BacktestingStrategy(BaseBarFeed barFeed, double cash) {

		super();

		BacktestingBroker broker = new BacktestingBroker(cash, barFeed);
		super._init(barFeed, broker);

		__useAdjustedValues = false;
		setUseEventDateTimeInLogs(true);
		setDebugMode(true);
	}

	/**
	 * @param barFeed The bar feed to use to backtest the strategy.
	 * @param broker  The starting capital or a broker instance.
	 */
	public BacktestingStrategy(BaseBarFeed barFeed, BacktestingBroker broker) {

		super(barFeed, broker);

		__useAdjustedValues = false;
		setUseEventDateTimeInLogs(true);
		setDebugMode(true);
	}

	/**
	 * XXX: Java requires calling super() at the entry of sub class constructor. Only used by sub
	 * classes.
	 */
	public BacktestingStrategy() {

		super();
	}

	/**
	 * XXX: Java requires calling super() at the entry of sub class constructor. Only used by sub
	 * classes.
	 */
	protected void _init(BaseBarFeed barFeed) {

		_init(barFeed, 1000000);
	}

	/**
	 * XXX: Java requires calling super() at the entry of sub class constructor. Only used by sub
	 * classes.
	 */
	protected void _init(BaseBarFeed barFeed, double cash) {

		BacktestingBroker broker = new BacktestingBroker(cash, barFeed);
		_init(barFeed, broker);
	}

	/**
	 * XXX: Java requires calling super() at the entry of sub class constructor. Only used by sub
	 * classes.
	 */
	protected void _init(BaseBarFeed barFeed, BacktestingBroker broker) {

		super._init(barFeed, broker);

		__useAdjustedValues = false;
		setUseEventDateTimeInLogs(true);
		setDebugMode(true);
	}

	/*
	 * (non-Javadoc)
	 * @see qy.jalgotrade.strategy.BaseStrategy#getUseAdjustedValues()
	 */
	@Override
	public boolean getUseAdjustedValues() {

		return __useAdjustedValues;
	}

	public void setUseAdjustedValues(boolean useAdjusted) throws Exception {

		getFeed().setUseAdjustedValues(useAdjusted);
		((BacktestingBroker) getBroker()).setUseAdjustedValues(useAdjusted);
		__useAdjustedValues = useAdjusted;
	}

	/**
	 * Enable/disable debug level messages in the strategy and backtesting broker. This is enabled by
	 * default.
	 * 
	 * @param debugOn
	 */
	public void setDebugMode(boolean debugOn) {

		Level level;
		if (debugOn) {
			level = Level.DEBUG;
		} else {
			level = Level.INFO;
		}
		// change Logger level at runtime (depend on actual logging impl, e.g.: logback):
		((Logger) getLogger()).setLevel(level);
		((Logger) ((BacktestingBroker) getBroker()).getLogger()).setLevel(level);
	}

	/**
	 * 
	 */
	public void changeLogLevel(Level level) {

		((Logger) getLogger()).setLevel(level);
	}
}
